package com.zhuiyun.project.security.jwt;

import com.zhuiyun.project.api.appuser.entity.User;
import com.zhuiyun.project.api.sysuser.entiy.SysUser;
import com.zhuiyun.project.api.sysuser.mapper.SysUserMapper;
import com.zhuiyun.project.common.errorCode.CommonException;
import com.zhuiyun.project.common.errorCode.EmErrorCode;
import com.zhuiyun.project.security.customizelogin.usernamepasswordcode.UsernamePasswordCodeAuthenticationToken;
import com.zhuiyun.project.security.customizelogin.wx.WechatAuthenticationToken;
import com.zhuiyun.project.util.ObjectUtils;
import com.zhuiyun.project.util.RedisUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName JWTAuthenticationTokenFilter
 * @Description JWT接口请求校验拦截器
 * 请求接口时会进入这里验证Token是否合法和过期
 * @Author zcy
 * @Date 2023/3/27 16:28
 **/
@Component
@Slf4j
public class JWTAuthenticationTokenFilter extends BasicAuthenticationFilter {
    @Autowired
    SysUserMapper SysUserMapper;

    public JWTAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    /**
     * 验证token
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     */
    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        // 获得TokenHeader
        //验证token格式是否正确
        if (JWTUtils.checkRequestToken(request)) {
            // 截取JWT前缀
            String token = JWTUtils.getToken(request);
            // 解析JWT
            boolean verify = JWTUtils.verify(token);
            //判断token类型
            String userType = JWTUtils.getInfo(token, "userType");
            //前端用户
            if (userType.equals("user")) {
                User user = null;
                try {
                    //从redis中取出user对象
                    user = (User) RedisUtil.get(token);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //判断从redis中去出来的内容是否为空
                if (verify && ObjectUtils.isNotEmpty(user)) {
                    // 获取用户名
                    String openId =JWTUtils.getInfo(token, "openId");
                    String userPhone = JWTUtils.getInfo(token, "userPhone");
                    //判断token和redis中的手机号是否一致
                    if (ObjectUtils.isNotEmpty(userPhone) && userPhone.equals(user.getUserPhone())) {
                        // 续约token
                        RedisUtil.expire(token, JWTConfig.expiration);
                        RedisUtil.expire(user.getUserPhone(), JWTConfig.expiration);
                        //获取该账号的权限
                        //获取用户信息
                        List<String> list = findPermissionByAdminUserName(user.getUserType());
                        List<GrantedAuthority> authorities = new ArrayList<>();
                        for (String permissionCode : list) {
                            if (permissionCode != null && permissionCode != "") {
                                GrantedAuthority grantedAuthority =
                                        new SimpleGrantedAuthority(permissionCode);
                                authorities.add(grantedAuthority);
                            }}
                        //获取用户权限信息
                        WechatAuthenticationToken wechatAuthenticationToken = new WechatAuthenticationToken(openId, userPhone, authorities);
                        // 将user对象交给SecurityContextHolder管理
                        SecurityContextHolder.getContext().setAuthentication(wechatAuthenticationToken);
                    } else {
                        // token中的loginName 与redis中的不符
                        throw new CommonException(EmErrorCode.TOKEN_INVALID);
                    }
                } else {
                    throw new CommonException(EmErrorCode.TOKEN_EXPIRE);
                }
            } else {
                //后台用户
                SysUser sysUser = null;
                try {
                    sysUser = (SysUser) RedisUtil.get(token);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (verify && ObjectUtils.isNotEmpty(sysUser)) {
                    String loginName = JWTUtils.getInfo(token, "loginName");
                    if (ObjectUtils.isNotEmpty(loginName) && loginName.equals(sysUser.getLoginName())) {
                        // 续约token
                        RedisUtil.expire(token, JWTConfig.expiration);
                        RedisUtil.expire(sysUser.getLoginName(), JWTConfig.expiration);
                        List<String> list = new ArrayList<>();
                        //系统用户
                        list.add("sys");
                        List<GrantedAuthority> authorities = new ArrayList<>();
                        for (String permissionCode : list) {
                            if (permissionCode != null && permissionCode != "") {
                                GrantedAuthority grantedAuthority =
                                        new SimpleGrantedAuthority(permissionCode);
                                authorities.add(grantedAuthority);
                            }}
                        UsernamePasswordCodeAuthenticationToken authentication  = new UsernamePasswordCodeAuthenticationToken(sysUser,authorities);
                        // 将user对象交给SecurityContextHolder管理
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    } else {
                        // token中的loginName 与redis中的不符
                        throw new CommonException(EmErrorCode.TOKEN_INVALID);
                    }
                } else {
                    throw new CommonException(EmErrorCode.TOKEN_EXPIRE);
                }
            }
        }
        filterChain.doFilter(request, response);
    }
    /**
     * @Author kdj
     * @Description 获取用户权限
     * @Date  10:00
     * @Return java.util.List<java.lang.String>
     * @param type
     */
    public static List<String>  findPermissionByAdminUserName(int type){
        List<String> list = new ArrayList<String>();
        //app用户权限
        list.add("app");
        //用户类型
        // 0 普通用户 1 医师
        if(type==0){
            //患者
            list.add("patient");
        }else{
            //医师
            list.add("physician");
        }
        return list;
    }
}
